package com.zzf.concurrent.example.design.pattern.read.writer;

/**
 * @author GaoFeng2017
 * @date 2019/9/6 20:16
 */
public class ReadWriterLock {

    /** 有多少个线程正在读 */
    private int readingReaders;
    /** 有多少个线程在等待读 */
    private int waitingReaders;
    /** 有多少个线程正在写 */
    private int writingWriters;
    /** 有多少个线程在等待写 */
    private int waitingWriters;
    /** 是否更偏向于写 */
    private boolean preferWrite;

    public ReadWriterLock() {
        this(true);
    }

    public ReadWriterLock(boolean preferWrite) {
        this.preferWrite = preferWrite;
    }

    public synchronized void readLock() {
        waitingReaders++;
        try {
            while (this.writingWriters > 0 || (this.preferWrite && this.waitingWriters > 0)) {
                this.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            waitingReaders--;
        }
        readingReaders++;
    }

    public synchronized void readUnLock() {
        readingReaders--;
        this.notifyAll();
    }

    public synchronized void writerLock() {
        waitingWriters++;
        try {
            while (this.readingReaders > 0 || this.writingWriters > 0) {
                this.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            waitingWriters--;
        }
        this.writingWriters++;
    }

    public synchronized  void writerUnLock() {
        this.writingWriters--;
        this.notifyAll();
    }

    public int getWaitingReaders() {
        return waitingReaders;
    }

    public int getWaitingWriters() {
        return waitingWriters;
    }
}
